//
// Author    : Pablo Bosch 
// Contact   : pboschvivancos@epo.org
// Last Modif: 13/03/2005
//

/*-------------------------------------------------------------------*/
/* Claim functions related to claim manipulation (no storage)        */
/*-------------------------------------------------------------------*/

// (A)pparatus, (M)ethod, (S)ystem, (P)roduct (T) Modulated data signal (M) Computer readable medium  

var MOD_CLAIMS={
  TAINTEDCLS:[],
  TAINTEDCNT:1
};


function ClaimTypeName(cl) {
  return kw_getCatName(GetClaimCategory(cl),GetDossierLang());
}

function ClaimTypeCapName(cl) {
  return tofirstcapital(ClaimTypeName(cl));
}

// return class for claim styling
function ClaimTypeStyle(cl) {
  var cat=GetClaimCategory(cl);
  if(is_clindependent(cl)) {
    return "CLINDEP "+kw_getColor1(cat); //CLINDEP"+GetClaimCategory(cl);
  } else {
    return "CLDEP "+kw_getColor2(cat); //GetClaimCategory(cl);
  }
} 

//---------------------------------------------------------------------------

function is_claim(cl) {
  return parseInt(cl) && (cl >=1 && cl <= CLAIMS.length);
}

//---------------------------------------------------------------------------

function select_list(clist,cond) {
  var iter  = new List_iterator(clist);
  var list_out=new List();
  while(!iter.end()) {
    if(cond(iter.getValue())) {
      list_out.push(iter.getValue());
    }
    iter.next();
  }
  return list_out;
}

//---------------------------------------------------------------------------

// select independent claims 
function select_indep(clist) { 
  return select_list(clist,claim_isgrpindependent).getValue();
}

//---------------------------------------------------------------------------

// select dependent claims 
function select_dep(clist) {
  return select_list(clist,claim_isgrpdependent).getValue();
}

//---------------------------------------------------------------------------

// select claims equivalent to some claim
function select_eq(clist) {
  return select_list(clist,GetClaimEq).getValue();
}

//---------------------------------------------------------------------------
// Used for cl^ claim lists 
function GetRootPath(cl) {
  var list_out=new List(cl);
  var dep=GetClaimDep(cl);  	
  while(dep && dep_isdependent(dep)) {
    list_out.push(dep);
    cl=dep;
    dep=GetClaimDep(cl);
  }  
  return list_out.getValue();
}

//---------------------------------------------------------------------------
function GetRootClaim(cl) {  	
  var dep=GetClaimDep(cl);  	
  while(dep && dep_isdependent(dep)) {
     cl=dep;
     dep=GetClaimDep(cl);
  }  
  return cl;
}

//---------------------------------------------------------------------------
function IsChildClaim(parent,child) {  	
  while(claim_isdependent(child)) {
    if(GetClaimDep(child) == parent) {
      return true;
    }     
    child=GetClaimDep(child);
  }  
  return false;
}
 
//---------------------------------------------------------------------------
// select claims dependent on claim cl_in 
function select_dep_on(cl_in) {
  var list_out="";
  var i;
  var _tmp=new Array();
  var cl_iter=new claim_iterator(1+cl_in);
  while(!cl_iter.end()) { 
    if(!is_clindependent(cl)) {
      var _deps_on=GetClaimDep(cl);
      if(_deps_on==cl_in) {
	_tmp[cl]=1;
      } else {
	for(var j  in _tmp ) {
	  if (_deps_on==j) {
	    _tmp[cl]=1;
	    break;
	  }
	}
      }
    }  
  }    
  return _tmp;
}

//---------------------------------------------------------------------------
// list of claims having a claim eq to them
function select_anti_eq(cList) {
  var iter  = new List_iterator(cList);
  var list_out="";
  while(!iter.end()) {
    if(GetClaimEq(iter.getValue())) {
      list_out+=GetClaimEq(iter.getValue())+",";
    }
    iter.next();
  }
  return rmlastchar(list_out);
}

// select claims equal to cl_in
function select_eq_to(cl_in,list_in) {
  var iter  = new List_iterator(list_in);
  var list_out=new List();	
  while(!iter.end()) {
    if(GetClaimEq(iter.getValue())==cl_in) {
      list_out.push(iter.getValue());
    }
    iter.next();
  }
  return list_out.getValue();
}

// select claims of category cat (M,A,S,P)
function select_cat_of(cat, List_in) {
  var iter  = new List_iterator(List_in);
  var list_out=new List();	
  while(!iter.end()) {
    if(GetClaimCategory(iter.getValue())==cat) {
      list_out.push(iter.getValue());
    } 
    iter.next();
  }
  return list_out.getValue();
}


// find claims
function claim_parents(cl) {
  var dep=cl;
  var deplist=new List();
  while(is_cldependent(dep)) {	
  	dep=GetClaimDep(dep);
  	deplist.push(dep);	   	    
  }  	
  return deplist.getValue();
}


// find claim descendants  in inlist

function claim_childrenlist(cl,inlist) {
  var deplist=new List();
  var iter = inlist ? inlist.iterator() : new claim_iterator(cl); 
  while(!iter.end()) {
    var child=iter.getValue();
    if(IsChildClaim(cl,child)) {       
	deplist.push(child);
    }
    iter.next();
  }
  return deplist;
}

function claim_children(cl,inlist) {
  return claim_childrenlist(cl,inlist).getValue();
}


// children of claims in list 
function list_children(eqlist) {   
  var iter  = new List_iterator(eqlist);
  var list_out= new List();
  while(!iter.end()) {    
    list_out.push(claim_children(iter.getValue()));    
    iter.next();
  }
  return list_out.unique();
}

function claim_equals(cl) {
  var eqlist=new List();
  for(var j=cl; j <= GetClaimSetLength() ; j++) {
    if(GetClaimEq(j)==cl) {
      eqlist.push(j);
    }
  }
  return eqlist.getValue();
}



//----------------------------------------------------------------------------------------------
// keep track of changed claims
//----------------------------------------------------------------------------------------------


function is_Tainted(cl) {
  return (MOD_CLAIMS.TAINTEDCNT==(MOD_CLAIMS.TAINTEDCLS[cl]));
}

function set_Tainted(cl) {
    MOD_CLAIMS.TAINTEDCLS[cl]=MOD_CLAIMS.TAINTEDCNT;
}

function new_Taint(cl) {
  ++MOD_CLAIMS.TAINTEDCNT;
  if(cl) {
     MOD_CLAIMS.TAINTEDCLS[cl]=MOD_CLAIMS.TAINTEDCNT;
  }
  return MOD_CLAIMS.TAINTEDCNT;
}
  
function get_Taint() {
  return MOD_CLAIMS.TAINTEDCNT;
}

function is_TaintedFrom(taint,cl) {
  return MOD_CLAIMS.TAINTEDCLS[cl]>=taint;
}


//----------------------------------------------------------------------------------------------


//
// Calculate Novelty/Inventiveness from documents
// (cl is not equal to someone else)

function is_clupgradable(cl,dep) {
  var depx=GetClaimDoc_X(dep);

  if(depx) {
    //alert("claim "+cl+" can be upgraded to X");
    return IsClaimFullFeatured(cl,depx) && "X";    
  }
  var depy=GetClaimDoc_Y(dep);
  if(depy) {
    //alert("claim "+cl+" can be upgraded to Y");
    return IsClaimFullFeatured(cl,depy) && "Y";
  }
  //alert("claim "+cl+" cannot be upgraded.");
  return "";
}

function _updatefromdocs(cl,dep) {
  var is_cldep=claim_isgrpdependent(cl); 
  if(is_cldep && IsClaimNovelandInventive(dep)) {
    // dependent on new and inventive 
    GrantClaim(cl,GetClaimDoc_A(dep));
    SetClaimValue(cl,GetClaimValue(dep));
  } else  { // independent or dependent on not new/inventive 
    if(is_cldep && !GetClaimStratFork(cl)) { // if dependent, check downgrade to parent's strat values  
      // If strategy fork treat as independent
      switch(is_clupgradable(cl,dep)) {
      case "X":
	SetClaimDoc_X(cl,GetClaimDoc_X(dep));
	break;
      case "Y":
	SetClaimDoc_Y(cl,GetClaimDoc_X(dep));
	break;
      default:
	// if X,Y1 check dep claim 
	var xdoc=GetClaimDoc_X(cl);
	if(xdoc) SetClaimDocStrat(cl,GetMinStrat(cl,dep,xdoc),xdoc);
	// if Y2, check dep value 
	var ydoc=GetClaimDoc_Y(cl);
	if(ydoc && (GetClaimDoc_A(dep)==ydoc || GetClaimDoc_B(dep)==ydoc || GetClaimDoc_C(dep)==ydoc)) {
	  SetClaimDocStrat(cl,GetMinStrat(cl,dep,ydoc),ydoc);
	}
      }
    }    
    // Assert claim value
    if(GetClaimDoc_X(cl)) {
      //alert("updatefromdocs X("+cl+")");
      if(GetClaimHint(cl) || GetClaimDoc_Y(cl) || GetClaimDoc_A(cl) || GetClaimDoc_B(cl) || GetClaimDoc_C(cl)) {
	//alert("updatefromdocsYAB("+cl+") Y=["+GetClaimDoc_Y(cl)+"] A=["+GetClaimDoc_A(cl)+"] B="+GetClaimDoc_B(cl)+" H=["+GetClaimHint(cl)+"] C=["+GetClaimDoc_C(cl)+"]");
	
	SetClaimNotInventive(cl);
      } else if(is_cldep && IsClaimNotInventive(dep)) {
	//alert("updatefromdocsDEP("+cl+")");
	SetClaimNotInventive(cl);
      } else {
	//alert("updatefromdocsNov("+cl+")");
	SetClaimNotNovel(cl);
      }
    } else if(GetClaimDoc_A(cl)) {
      //alert("new and invent searched("+cl+")");
      SetClaimNovelandInventive(cl);
    } else {
      //alert("updNot searched("+cl+")");
      SetClaimNotSearched(cl);
    }
  } 
}


// compute claim value from docs 
function updatefromdocs(cl) {
  var eq=GetClaimEq(cl);
  var dep=GetClaimDep(cl);
  //alert("doupdatefromdocs("+cl+","+dep+")");
  if(eq && (is_Tainted(eq) || is_Tainted(dep))) {
    //alert("changeEq("+cl+","+eq+")");    
    changeEq(cl,eq);
  } else if(is_Tainted(cl) || is_Tainted(dep)) { // not equal claim     
    // depends on new and inventive
    //alert("doupdatefromdocs("+cl+","+dep+")");
    _updatefromdocs(cl,dep);
  }  
}

// update when no doc is used 
function updatemanual(cl) {
  var dep=GetClaimDep(cl);
  var eq = GetClaimEq(cl);
  
  if(dep) {
    if(eq) {
      if(claim_isgrpindependent(cl) || IsClaimNotNovel(dep) || IsClaimNovelandInventive(eq)) {
	SetClaimValue(cl,GetClaimValue(eq));
	return;
      }
    } 
    if(IsClaimNovelandInventive(cl)){
      return;
    }
    if(claim_isgrpdependent(cl)) {
      if(IsClaimNovelandInventive(dep)) {
	SetClaimNovelandInventive(cl);
	return;
      }
      if(IsClaimNotInventive(dep)) {
	SetClaimNotInventive(cl);
      }
    }
  }
}

//
// Check if we can upgrade a document value for a claim equivalent to another claim  
// 
function is_equpgradable(cl,dep,eq,eqdep) {
  if(is_clindependent(eqdep)) {  // if eq depends on independent, there is no downgrading of eq
    return "";  // cannot be upgraded 
  }
  var depx=GetClaimDoc_X(dep);
  if(depx) {
    if(GetClaimDoc_Y(eqdep)==depx || GetClaimDoc_A(eqdep)==depx) {
      alert("claim "+cl+" can be upgraded to X");
      return IsClaimFullFeatured(eq,depx) && "X";
    }
  }
  var depy=GetClaimDoc_Y(dep)
  if(depy) {
    if(GetClaimDoc_A(eqdep)==depy) {
      alert("claim "+cl+" can be upgraded to Y");
      return IsClaimFullFeatured(eq,depy) && "Y";
    }
  }
  //alert("claim "+cl+" cannot be upgraded.");
  return "";
}

// Change Eq field of claim cl to eqcl
// If new eq exists, translate doc vals
//                   copy claim val from eqcl (in case no docs and forced value) but 
//                   check for its parent claim inventiveness
// If new eq is empty, mark claim not searched

function changeEq(cl,eqcl) {
  var dep=GetClaimDep(cl);
  var oldeq=GetClaimEq(cl);

  if(SetClaimEq(cl,eqcl)==XML_CLM.ERR_NO) {
    
    if(eqcl) {
      if(is_cldependent(cl)) { // dependent claim
	if(!IsClaimSearched(dep)){
	  SetClaimNotSearched(cl);
	  return;
	}
	if(IsClaimNovelandInventive(dep)) { // depend on novel and inventive
	  GrantClaim(cl,GetClaimDoc_A(dep));
	  return;
	}                            // depend on smth else 
	if(GetClaimDoc_X(eqcl)) {
	  SetMinStrat(cl,eqcl,dep,GetClaimDoc_X(eqcl)); // respect dep 
	  SetClaimDoc_Y(cl,GetClaimDoc_Y(eqcl));
	  SetClaimDoc_A(cl,GetClaimDoc_A(eqcl));
	  SetClaimDoc_B(cl,GetClaimDoc_B(eqcl));	  
	  SetClaimDoc_C(cl,GetClaimDoc_C(eqcl));	  
	  SetClaimHint(cl,GetClaimHint(eqcl));	  	  
	} else {
	  SetClaimDoc_X(cl,"");
	  switch(is_equpgradable(cl,dep,eqcl,GetClaimDep(eqcl))) {
	  case "X":	    
	    _SetClaimDoc_X(cl,GetClaimDoc_X(dep));	    
	  case "Y":
	    SetClaimDoc_Y(cl,GetClaimDoc_Y(dep));
	    SetClaimDoc_A(cl,"");
	    SetClaimDoc_B(cl,"");
	    SetClaimDoc_C(cl,"");
	    SetClaimHint(cl,"");
	    SetClaimValue(cl,GetClaimValue(dep));
	    return;
	  default:
	    //alert("claim "+cl+" is not upgraded to X="+GetClaimDoc_X(cl));
	    SetClaimDoc_Y(cl,GetClaimDoc_Y(eqcl));
	    SetClaimDoc_A(cl,GetClaimDoc_A(eqcl));
	    SetClaimDoc_B(cl,GetClaimDoc_B(eqcl));      	  
	    SetClaimDoc_C(cl,GetClaimDoc_C(eqcl));	  
	    SetClaimHint(cl,GetClaimHint(eqcl));	  	  

	    if(IsClaimNotNovel(eqcl) || IsClaimNotInventive(eqcl)) {
	      if(GetClaimDoc_X(dep)!=GetClaimDoc_X(eqcl)) {
		SetClaimNovelandInventive(cl);
		return;
	      }	  
	    }    
	    if(IsClaimNotNovel(eqcl)) {
	      SetClaimDoc_B(cl,"");
	      if(IsClaimNotInventive(dep)) {	  
		SetClaimNotInventive(cl);
		return;
	      } 
	    } 
	    SetClaimValue(cl,GetClaimValue(eqcl));
	    return;		    
	  } // end switch
	}
      } 
      // independent claim
      SetClaimDoc_X(cl,GetClaimDoc_X(eqcl));
      SetClaimDoc_Y(cl,GetClaimDoc_Y(eqcl));
      SetClaimDoc_A(cl,GetClaimDoc_A(eqcl));
      SetClaimDoc_B(cl,GetClaimDoc_B(eqcl));      
      SetClaimValue(cl,GetClaimValue(eqcl));     
      SetClaimDoc_C(cl,GetClaimDoc_C(eqcl));	  
      SetClaimHint(cl,GetClaimHint(eqcl));	  	  
    }  else { //clear equivalence 
      update_B_hints(cl,GetClaimDoc_X(cl));
      _updatefromdocs(cl,GetClaimDep(cl));
    }
  }
}


// Change document for category cat if was olddoc 
function setcldoccatdoc(cl,cat,olddoc,newdoc) {
  eval("if(GetClaimDoc_"+cat+"("+cl+")=="+"\""+olddoc+"\") SetClaimDoc_"+cat+"("+cl+",\""+newdoc+"\");");
}

//
// Propose claims to propagate changes to (dependent) 
//

function prompt_downwards_propagation(cl,catsel,seldoc) {
  var children=claim_children(cl);
  if(children) {
    var rep=prompt("Propagate to (only claims on same group)",List_tolist(children));
    if(rep && rep!="") {
      return list_toList(rep);
    }
  }
  return "";
}



/* The mother of all functions */
// IN cl1: claim to apply changes
// IN clist: list of other claims to apply changes 
// clist should not contain claims < cl1. Well now it can !!!

function change_stratdoc_claimlist(cl1,clist,catsel,seldoc) {
  // list of claims to modify (explicitly) 
  var mod_list= new List();
  if(cl1) {
    mod_list.push(cl1);
  }
  if(clist) {
    mod_list.push(list_toList(clist));
  }

  var mod_iter=mod_list.iterator();
  var modcl  = mod_iter.getValue();
  var cl_iter= new claim_iterator(modcl);
  var ignored= new List();

  while(!cl_iter.end()) {
    var cl=cl_iter.getValue();   // current claim 
    if(!mod_iter.end() && modcl < cl) {
      alert("Ooops, malformed claim list: ["+mod_list.getValue()+"]"+modcl+" < "+cl);
      return;
    } 
    //alert(cl+" T"+get_Taint(cl)+" H1  "+GetClaimHint(cl));
    if(cl == modcl) { // claim to update explicit
      if(SetClaimDocStrat(cl,catsel,seldoc)==XML_CLM.ERR_NO) {
	//alert(cl+" T"+get_Taint(cl)+" H11  "+GetClaimHint(cl));
	//alert("Update "+cl+" with "+catsel+" for "+seldoc+" = "+GetClaimDocStrat(cl,seldoc));
	updatefromdocs(cl);
	//alert("After from docs  = "+GetClaimDocStrat(cl,seldoc));

      } else { // cannot update this claim 
	ignored.push(cl);
      }
      if(!mod_iter.end()) {
	mod_iter.next();
	modcl=mod_iter.getValue();	
      }
    } else {
      // claim to update implicit
      //alert(cl+":  H21 "+GetClaimHint(cl));
      updatefromdocs(cl);
      //alert(cl+":  H22 "+GetClaimHint(cl));
    }
    cl_iter.next();
  } 

  // second round 
  mod_iter.reset();

  new_Taint(); // previous taint is obsolete this is 2nd round 
  var restartcl;
  while(!mod_iter.end()) { // empty list  
    modcl=mod_iter.getValue();
    if(is_clindependent(modcl)) {
      var eq_iter=new Eq_claim_iterator(modcl);
      while(!eq_iter.end()) {
	if(eq_iter.getValue()<modcl) {
	  if(!restartcl || eq_iter.getValue()<restartcl) {
	    restartcl=eq_iter.getValue();
	  }
	  set_Taint(modcl); // force reevaluation
	}
	eq_iter.next();
      }
    }
    mod_iter.next();
  }
  //alert(cl+": H3 "+GetClaimHint(cl));
  // 2nd round
  if(restartcl) {
    cl_iter= new claim_iterator(restartcl);
    while(!cl_iter.end()) {
      //alert("2nd round "+cl_iter.getValue());
      updatefromdocs(cl_iter.getValue());
      cl_iter.next();
    }
  }
  //alert(cl+ ": H4 "+GetClaimHint(cl));
}



function split_claims(ilist,notclear,notnew,notinv,ok,noop) {
  var cl_iter= new List_iterator(ilist);
  while(!cl_iter.end()) {
    var cl=cl_iter.getValue();
	//alert(cl+" is "+GetClaimValue(cl));      
        switch(GetClaimValue(cl)) {
           case "XN":
		notnew.push(cl);
                break;
           case "XI":
		notinv.push(cl);
                break;
           case "A":
		ok.push(cl);
 		break;
           case "??":	
 	        noop.push(cl);
                break;
        }
	if(IsClaimUnclear(cl)) notclear.push(cl);
    
    cl_iter.next();
  }
}

function select_claims_unclear(clist) {
  var cl_iter= new List_iterator(clist);
  var out= new List();
  while(!cl_iter.end()) {
    var cl=cl_iter.getValue();
    if(!IsClaimClear(cl)) {
      out.push(cl);
    }
    cl_iter.next();
  }
  return out.getValue();
}

function _GetAllClaims(cat) {
  var clist = new List();
  var cl_iter=new filteredclaims_iterator();
  while(!cl_iter.end()) {
    if(cat==GetClaimValue(cl_iter.getValue()))   {	
      clist.push(cl_iter.getValue());
    }
    cl_iter.next();
  }
  
  return clist.getValue();
}

function _GetAllUClaims() {
  var clist = new List();
  var cl_iter=new filteredclaims_iterator(); 
  while(!cl_iter.end()) {
    if(IsClaimUnclear(cl_iter.getValue()))   {	
      clist.push(cl_iter.getValue());
    }
    cl_iter.next();
  }  
  return clist.getValue();
}

function _GetAllGClaims(g) {
  var clist = new List();
  var cl_iter=new filteredclaims_iterator(); 
  while(!cl_iter.end()) {
    if(GetClaimGroup(cl_iter.getValue()) == g)   {	
      clist.push(cl_iter.getValue());
    }
    cl_iter.next();
  }    
  return clist.getValue();
}

  
function GetAllClaims(cat) {
  switch(cat) {
	case "U":
		return _GetAllUClaims();
        case "XN":
        case "XI":
        case "A":
	case "??":
	 	return _GetAllClaims(cat);
	default: 
		return _GetAllGClaims(cat);
  }
}
